package com.tangtang.hystrix.provider.controller;

import com.alibaba.fastjson.JSONObject;
import com.tangtang.hystrix.provider.command.BrandThreadCommand;
import com.tangtang.hystrix.provider.command.ProductCommand;
import com.tangtang.hystrix.provider.command.ProductObservableCommand;
import com.tangtang.hystrix.provider.vo.BrandVO;
import com.tangtang.hystrix.provider.vo.OrderVO;
import com.tangtang.hystrix.provider.vo.ProductVO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import rx.Observer;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@RestController
@RequestMapping("/api/v1/order")
public class OrderController {
    @GetMapping("{id}")
    public OrderVO getOrder(@PathVariable("id") Long orderId){
        OrderVO orderVO = new OrderVO();
        orderVO.setId(1L);
        orderVO.setDate(new Date());

        orderVO.setOrderNo(System.currentTimeMillis());
        List<ProductVO> products = new ArrayList<>();
        orderVO.setProducts(products);
        ProductVO product2 = null;
        try {
            //同步执行
            ProductVO product1 = new ProductCommand(1L).execute();
            addProduct(orderVO, products, product1);
            //同步执行
            product2 = new ProductObservableCommand(2L).observe().toBlocking().toFuture().get();
            addProduct(orderVO, products, product2);

            //异步执行
            Future<ProductVO> queue = new ProductCommand(2L).queue();
            //执行一些额外的操作
            Thread.sleep(500L);
            ProductVO product3 = queue.get();
            addProduct(orderVO,products,product3);
            //异步执行
            Future<ProductVO> productFuture = new ProductObservableCommand(4L).observe().toBlocking().toFuture();
            Thread.sleep(500L);
            ProductVO product4 =  productFuture.get();
            addProduct(orderVO, products, product4);

            new ProductObservableCommand(5L).observe().subscribe(new Observer<ProductVO>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(ProductVO productVO) {
                    System.out.println(JSONObject.toJSON(productVO));
                }
            });

            new ProductCommand(6L).toObservable().subscribe(new Observer<ProductVO>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(ProductVO productVO) {
                    System.out.println(JSONObject.toJSON(productVO));
                }
            });
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(product2);


        orderVO.getProducts().forEach(productVO -> {
            Long brandId = productVO.getBrandId();
            try {
                BrandThreadCommand brandThreadCommand = new BrandThreadCommand(brandId);
                BrandVO brandVO =  brandThreadCommand.observe().toBlocking().toFuture().get();
                boolean responseFromCache = brandThreadCommand.isResponseFromCache();
                System.out.println("从缓存中读取的："+responseFromCache);
                productVO.setBrandVO(brandVO);
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });
        return orderVO;
    }

    private void addProduct(OrderVO orderVO, List<ProductVO> products, ProductVO product) {
        products.add(product);
        if(orderVO.getSumPrice() !=null){
            orderVO.setSumPrice(orderVO.getSumPrice().add(product.getPrice()));
        }else{
            orderVO.setSumPrice(product.getPrice());
        }
    }
}
